<!--
 * 调研工作安排 - 主要行程/调研报告/调研须知/审批意见
-->
<template>
  <div class="arrangement-form">
    <jdf-form-collapse ref="formCollapse" :list.sync="list">
      <!-- 主要行程 -->
      <template #mainItineraries>
        <div class="main-schedule">
          <jdf-form-dynamic-table
            ref="dynamicTable"
            v-model="form.mainItineraries"
            :columns="columns"
            :column-attrs="columnsAttrsAll"
            :is-edit="fieldIsEdit('mainItineraries')"
            :rules="rules"
            lineClamp
            :btnIsTop="true"
            dialog-width="70%"
            :show-btns="showBtns"
            :importAttrs="importAttrs"
            @importCallback="importCallback"
          ></jdf-form-dynamic-table>
        </div>
      </template>
      <!-- 调研报告 -->
      <template #researchReport>
        <div>
          <jdf-increased-form
            ref="researchReportRef"
            :configs="reportConfigs"
            :form-attrs="formAttrs"
            :rules="rules"
            :data="form"
          />
        </div>
      </template>
      <!-- 调研须知 -->
      <template #researchGuidelines>
        <div>
          <jdf-increased-form
            ref="researchInstructionsRef"
            :configs="guideConfigs"
            :form-attrs="formAttrs"
            :rules="rules"
            :data="form"
          />
        </div>
      </template>
    </jdf-form-collapse>
    <!-- 当前环节可编辑 或者 已经点击了承诺 则展示 -->
    <el-radio v-if="isShowPromiseBtn" v-model="form.promiseId" :label="true">{{ WORK_ARRANGEMENT_COMMITMENT }}</el-radio>
    <el-dialog
      v-if="guidelinesVisible"
      :close-on-click-modal="false"
      :show-close="false"
      append-to-body
      width="70%"
      :visible.sync="guidelinesVisible"
      title="调研接待及材料规范"
    >
      <!-- TODO:数据源此版本先固定内容 后续完善需求 -->
      <div class="guidelines-dialog" v-html="guidelinesContent"></div>
      <div slot="footer" style="text-align: center" class="dialog-footer">
        <template v-if="isCountdown">
          <el-button v-if="readTimeFinish" type="primary" @click="handleRead">开始答题</el-button>
          <el-button v-else class="read-time" type="primary" disabled>
            <el-statistic ref="statistic" :format="countdownFormat" :value="readCountdown" time-indices @finish="timeFinish">
            </el-statistic>
          </el-button>
        </template>
        <template v-else>
          <el-button type="primary" @click="guidelinesVisible = false">关闭</el-button>
        </template>
      </div>
    </el-dialog>

    <quiz-dialog
      v-if="quizVisible"
      ref="quizDialogRef"
      :visible.sync="quizVisible"
      :service="service"
      width="70%"
      title="关于贯彻中央八项规定精神学习教育的问答"
      @submit="submitAnswers"
    ></quiz-dialog>
  </div>
</template>

<script>
import { renderLink, downloadFile, pickerBetweenOptions } from 'jdf-util';
import dayjs from 'dayjs';
import ResearchFormService from '@/api/domains/ResearchFormService';
import draftMixins from '@/mixins/draftMixins';
import {
  CANNOT_EDIT,
  CAN_EDIT,
  WORK_ARRANGEMENT_COMMITMENT,
  COUNTDOWN_TIME,
  ANSWER_FULL_MARKS,
  DEFAULT_DATE_FORMAT,
} from '@/utils/constants';
import {
  message, messageTipConfirm, showErrorMsg, validateMessage,
} from '@/api/utils/pc-message';
import { answerConfirmSubmitTip, cleanHtml, dateSelectionRange } from '@/utils/utils';
import { isEmpty, pick } from 'lodash-es';
import { WORK_GUIDELINES_CONTENT } from '@/utils/workGuidelines';
import QuizDialog from './QuizDialog';
import { getStorageInfo } from '@/api/utils/storage-util';
// 获取倒计时开始时间
const { COUNTDOWN_START_TIME } = COUNTDOWN_TIME;

export default {
  components: { QuizDialog },
  mixins: [draftMixins],
  name: 'ArrangementForm',
  props: {
    formData: {
      type: Object,
      default: () => ({}),
    },
    nodeId: {
      type: String,
      default: '',
    },
    fieldIsEdit: {
      type: Function,
      default: () => {},
    },
    isDone: {
      type: Boolean,
      default: false
    },
    piid: {
      type: String,
      default: ''
    },
  },
  data() {
    return {
      guidelinesContent: cleanHtml(WORK_GUIDELINES_CONTENT),
      WORK_ARRANGEMENT_COMMITMENT,
      service: new ResearchFormService(),
      // 阅读时间是否完成
      readTimeFinish: false,
      countdownFormat: '阅读 s 秒',
      form: {
        // 主要行程数据
        mainItineraries: [],
        // 是否已答题
        whetherAnswer: false,
        // 指出的问题
        indicatedProblem: '',
        // 作出的要求
        require: '',
        // 承诺
        promiseId: false,
      },
      rules: {
        itineraryTime: [{ required: true, trigger: 'change', message: '日期不能为空！' }],
        itineraryLocation: [{ required: true, trigger: 'blur', message: '地点不能为空！' }],
        mainArrangement: [{ required: true, trigger: 'blur', message: '主要安排不能为空！' }],
        indicatedProblem: [
          { required: true, trigger: 'blur', message: '指出的问题不能为空！' },
          { min: 50, message: '指出的问题最少输入50字以上！', trigger: 'blur' }
        ],
        require: [
          { required: true, trigger: 'blur', message: '作出的要求不能为空！'},
          { min: 100, message: '作出的要求最少输入100字以上！', trigger: 'blur',}
        ]
      },
      // 主要行程表格按钮
      showBtns: ['add', 'del'],
      // 表格列导入属性
      importAttrs: {
        'import-func': this.importFunc,
        'download-template-func': this.downLoadTemplate,
        'auto-upload': true,
        'download-template': true
      },
      importFileList: {},
      // 表格列公共属性，为所有列都具备的属性
      columnsAttrsAll: {
        align: 'center',
      },
      // 调研须知弹窗显示状态
      guidelinesVisible: false,
      // 答题弹窗显示状态
      quizVisible: false,
      // 表单属性
      formAttrs: {},
      // 主要行程表格列
      columns: [
        {
          label: '',
          type: 'selection',
          width: 55,
          hideInFormItem: true,
        },
        {
          label: '序号',
          type: 'index',
          width: 55,
          hideInFormItem: true,
        },
        {
          label: '日期',
          prop: 'itineraryTime',
          width: 150,
          editable: '1',
          itemType: 'DatePicker',
          itemColSpan: 24,
          itemAttrs: {
            'value-format': DEFAULT_DATE_FORMAT,
            format: DEFAULT_DATE_FORMAT
          },
          itemEvents: {
            focus: this.itineraryDateFocus,
            change: this.itineraryDateChange,
          }
        },
        {
          label: '地点',
          prop: 'itineraryLocation',
          width: 150,
          editable: '1',
          itemType: 'input',
          itemColSpan: 24,
        },
        {
          label: '主要安排',
          prop: 'mainArrangement',
          width: 150,
          editable: '1',
          itemType: 'input',
          itemColSpan: 24,
          itemAttrs: {
            type: 'textarea',
          },
        },
      ],
      // 调研须知配置
      reportConfigs: [
        [
          {
            formElCode: 'indicatedProblem',
            formElName: '指出的问题',
            editable: this.isResearchReportEdit('researchReport'),
            colSpan: 24,
            attrs: {
              placeholder: '文本，字数50字以上',
              type: 'textarea',
              rows: 2,
            },
          },
        ],
        [
          {
            formElCode: 'require',
            formElName: '作出的要求',
            editable: this.isResearchReportEdit('researchReport'),
            colSpan: 24,
            attrs: {
              placeholder: '文本，字数100字以上',
              type: 'textarea',
              rows: 2,
            },
          },
        ],
      ],
      // 调研须知配置
      guideConfigs: [
        [
          {
            formElCode: 'researchTips',
            formElName: '调研须知',
            colSpan: 24,
            render: (h, params) => renderLink(h, '点击查看调研须知', () => {
              // 打开调研须知弹窗 并开启倒计时
              this.readGuidelines();
            }),
          },
        ],
        [
          {
            formElCode: 'researchQuiz',
            formElName: '调研测验',
            colSpan: 24,
            render: (h, params) => {
              // 如果已经通过 则无需重复答题
              if(this.form.whetherAnswer) {
                return h('div', [h('el-link', {
                  props: {
                    type: 'success',
                    size: 'mini',
                    underline: false,
                    plain: true
                  }}, '已通过')
                ]);
              }

              // 默认为不通过
              return h('div', [h('el-link', {
                props: {
                  type: 'primary',
                  size: 'mini',
                  underline: false,
                  plain: true,
                  disabled: !this.fieldIsEdit('researchGuidelines')
                },
                on: {
                  click: this.readGuidelines
                }}, '点击开始答题')
              ]);
            }
          },
        ],
      ],
      // 表单配置
      list: [
        {
          slot: 'mainItineraries',
          title: '主要行程',
        },
        {
          slot: 'researchReport',
          title: '调研报告',
          notice: '（由调研组联络人填写）',
        },
        {
          slot: 'researchGuidelines',
          title: '调研须知',
          notice: '（由被调研组联络人填写）',
        },
      ],
      // 答题列表
      questionList: [],
      // 倒计时总秒数
      readCountdown: '',
      // 存储倒计时定时器
      countdownInterval: null,
      // 需要获取的字段
      needFields: [
        'mainItineraries',
        'indicatedProblem',
        'require',
      ]
    };
  },

  watch: {
    /**
     * 表格数据
     */
    form: {
      handler(val) {
        this.$emit('change-v', val);
      },
      deep: true
    },

    // 承诺 发生变化时 保存答题状态和承诺
    'form.promiseId': {
      handler(val) {
        val && this.saveAnswerStatus();
      }
    }
  },

  computed: {
    /**
     * 判断是否需要倒计时按钮
     */
    isCountdown() {
      const { fieldIsEdit, form: { whetherAnswer } } = this;
      // 如果是必填 并且 未答题成功时 则需要倒计时按钮
      return fieldIsEdit('researchGuidelines') && !whetherAnswer
    },

    /**
     * 是否展示承诺
     */
    isShowPromiseBtn() {
      const { nodeId, formData } = this;
      // 当前环节在'联络人办理' 且 当前登录人是'被调研单位联络人' 展示承诺按钮
      return nodeId === 'reassignTask' && formData?.conductResearchContactId === getStorageInfo('loginName');
    }
  },

  async mounted() {
    const { isShowPromiseBtn, form, confirmPromise, getFormInfo, getAnswerAndPromise } = this;
    // 数据回显
    getFormInfo();
    // 获取答题/承诺信息
    await getAnswerAndPromise();
    // 承诺表单可展示 并且 没有点击承诺时 打开弹窗提示用户确认
    isShowPromiseBtn && !form.promiseId && confirmPromise();
  },

  methods: {
    /**
     * 调研报告是否可编辑
     * @param {String} field 字段名
     */
    isResearchReportEdit(field) {
      const { nodeId, formData: { researchContactId } } = this;
      // 当前环节在'联络人办理' 并且 当前登录人为'调研组联络人' 这可编辑调研报告
      return nodeId === 'reassignTask' && researchContactId === getStorageInfo('loginName') ? CAN_EDIT : CANNOT_EDIT;
    },

    /**
     * 保存答题状态和承诺
     */
    async saveAnswerStatus() {
      const { piid, form: { whetherAnswer, promiseId: whetherCommit } } = this;
      try {
        const param = {
          piid,
          whetherAnswer,
          whetherCommit
        };
        await this.service.saveBizStatus(param);
      } catch (error) {
        showErrorMsg(error);
      }
    },

    /**
     * 承诺确认
     */
    confirmPromise() {
      // 提示用户查看承诺并确认
      messageTipConfirm(WORK_ARRANGEMENT_COMMITMENT, () => {
        this.form.promiseId = true;
      }, null, '温馨提示！', { customClass: 'send-message-box' })
    },

    /**
     * 查看调研须知并开始答题
     */
    readGuidelines() {
      // 打开调研须知弹窗 并开启倒计时
      Object.assign(this, { guidelinesVisible: true, readTimeFinish: false });
      this.restCountdown();
    },

    /**
     * 数据回显
     */
    getFormInfo() {
      const { form, formData, needFields } = this;
      Object.assign(form, pick(formData, needFields));
    },

    /**
     * 获取答题和承诺
     */
    async getAnswerAndPromise() {
      try {
        const data = await this.service.getAnswerAndPromise({ piid: this.piid });
        const { whetherAnswer, whetherCommit: promiseId } = data || {};
        Object.assign(this.form, { whetherAnswer, promiseId });
      } catch (error) {
        showErrorMsg(error);
      }
    },

    /**
     * 判断字段是否可编辑
     * @param field 字段名称
     */
    isEditable(field) {
      return this.fieldIsEdit(field) ? CAN_EDIT : CANNOT_EDIT;
    },

    /**
     * 主要行程表格数据日期选择范围
     */
    pickerOptions() {
      const [startTime, endTime] = this.formData.researchDateRange;
      return pickerBetweenOptions(startTime, endTime);
    },

    /**
     * 主要行程日期选择前校验
     * @param pickerIns {Object} 选择器实例
     */
    itineraryDateFocus(pickerIns) {
      // 如果有选择调研日期 则不需要校验
      if (this.formData.researchDate) {
        return;
      }
      // 如果没有选择调研起止日期 则提示并关闭选择器
      validateMessage('请先选择调研起止日期！');
      this.$set(pickerIns, 'pickerVisible', false);
    },

    /**
     * 主要行程日期选择后校验
     * @param time {Number} 选择的时间戳
     * @param data {Object} 当前表单的数据
     * @param $set {Function} 修改表单数据的方法
     */
    itineraryDateChange(time, data, $set) {
      // 获取调研开始时间和结束时间
      const { researchStartDate, researchEndDate } = this.formData;
      // 判断选择的时间是否在范围之内
      const isTimeScope = dateSelectionRange([researchStartDate, researchEndDate], time);
      if (isTimeScope) {
        return;
      }
      $set('itineraryTime', '');
      validateMessage('主要行程日期需在调研起止内，请您重新选择！');
    },

    /**
     * 重置倒计时(默认10s)
     */
    restCountdown() {
      this.readCountdown = dayjs().add(COUNTDOWN_START_TIME, 'second').valueOf();
    },

    /**
     * 倒计时结束
     */
    timeFinish() {
      this.readTimeFinish = true;
    },

    /**
     * 已阅读
     */
    handleRead() {
      // 关闭调研须知弹窗 打开调研测验弹窗 开始答题
      this.guidelinesVisible = false;
      this.$nextTick(() => {
        this.quizVisible = true;
      })
    },

    /**
     * 下载模板方法
     */
    async downLoadTemplate() {
      try {
        const data = await this.service.downloadTemplate();
        downloadFile(data);
      } catch (error) {
        showErrorMsg(error);
      }
    },

    /**
     * 导入文件
     * @param file {Object} 文件对象
     */
    importFunc(file) {
      const { researchStartDate, researchEndDate } = this.formData;
      // 如果没有选择调研起止日期 则阻止上传 提示并返回
      if (!researchStartDate && !researchEndDate) {
        validateMessage('请先选择调研起止日期！');
        throw new Error();
      }
      this.importFileList = file;
    },

    /**
     * 导入成功回调
     */
    async importCallback() {
      try {
        const { importFileList, formData: { researchStartDate, researchEndDate } } = this;
        const formList = new FormData;
        formList.append('file', importFileList);
        formList.append('startDate', researchStartDate);
        formList.append('endDate', researchEndDate);
        const { data: { data } } = await this.service.importMainItinerary(formList);
        // 如果为空 无需添加到表单中
        !isEmpty(data) && this.$set(this.form, 'mainItineraries', data);
      } catch (error) {
        showErrorMsg(error);
      }
    },

    /**
     * 提交答案
     * @param answerScore {number} 答题分数
     */
    async submitAnswers(answerScore) {
      // 获取答题交卷提示
      const { FULL_SCORE, NOT_FULL_MARKS } = answerConfirmSubmitTip(answerScore);
      // 如果是满分100 则提示并关闭弹窗
      if (answerScore === ANSWER_FULL_MARKS) {
        // 答题成功后 修改答题状态
        this.form.whetherAnswer = true;
        // 保存当前答题状态 并关闭弹窗 增加友好提示
        await this.saveAnswerStatus();
        this.quizVisible = false;
        message(FULL_SCORE);
        return;
      }
      // 如果为满分100 则提示并重新获取题目作答
      message(NOT_FULL_MARKS);
      this.$refs.quizDialogRef.getQuestionList();
    }
  },
};
</script>
<style lang="scss" scoped>
::v-deep.arrangement-form {
  width: 100%;
  .jdf-form-collapse .el-collapse-item__header .notice {
    color: red;
    font-size: 14px;
    margin-left: 10px;
    font-style: normal;
  }
  .main-schedule .jdf-form-dynamic-table {
    display: flex;
    flex-direction: column-reverse;
  }
}
::v-deep.read-time .el-statistic .con .number {
  font-size: 14px;
  color: #fff;
  font-weight: normal;
}

::v-deep .el-table__empty-block {
  width: 100% !important;
}

::v-deep .el-form-item__error {
  display: none !important;
}

::v-deep.guidelines-dialog {
  .work-guidelines-title {
    text-align: center;
  }
  .work-guidelines-body p {
    font-size: 16px;
    line-height: 24px;
  }
  text-indent: 2em;
}
</style>
